home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
436_01
/
infloat.c
< prev
next >
Wrap
Text File
|
1994-10-07
|
15KB
|
557 lines
/*************************************************************************
Source file: INFLOAT.C
INCON floating-point input handler.
Compiler: Borland Turbo C 2.01
INCON source files and the object and library files created from
them are:
Copyright (c) 1993-94, Richard Zigler.
You may freely distribute unmodified source, object, and library
files, and incorporate them into your own non-commercial software,
provided that this paragraph and the program name and copyright
strings defined in INCON.C are included in all copies.
*************************************************************************/
#include <ctype.h> /* character classification */
#include <string.h>
#include "indefs.h" /* globals and definitions */
#include "incon.h" /* state definitions */
#include "indecl.h" /* public utility routines */
/**** Local Data ****/
enum /* float field fix-up constants */
{
FLT_INIT , /* initialize field for display */
FLT_FIX , /* fix field left of decimal */
FLT_MOV , /* move chars left of decimal */
FLT_PAD , /* pad out field with zeros */
} ;
static BFLAG Point ; /* decimal point entered yet? */
static short PointNdx ; /* decimal point index */
static BFLAG Sign ; /* sign entered yet? */
static short SignNdx ; /* numeric sign index */
/**** Local Routines ****/
static int near pascal FloatFix
(
int Op, /* operation requested */
int Pos /* index into string */
) ;
int pascal hFloatField( STATES State, register int Pos )
{
register int max_width = Width - 1;
int old_pos = Pos;
switch( State )
{
case stError:
break;
case stQuit: /* [Enter] -- end input */
Chr = 0;
goto __FloatExit;
case stInit: /* field initialization */
SignNdx = 0;
Point = Sign = NO;
StrLength = Width;
if ( !Prec )
{
Prec = strchr( OutStr, '.' ) - OutStr;
Prec = StrLength - Prec - 1;
}
PointNdx = Width - Prec - 1;
if ( !PointNdx )
{
--Prec; /* force at least one decimal */
++PointNdx; /* digit position */
}
if ( PointNdx > 0 )
{
Flags.Confirm =
Flags.Display = YES;
Pos = FloatFix( FLT_INIT, 0 );
}
return ( Pos );
case stFieldClear: /* [Esc] -- clear field or exit */
if ( EscSet)
More = NO;
else
{
memset( OutStr, Fill, Width );
OutStr[PointNdx] = '.';
Pos =
SignNdx =
Sign = 0;
++Update;
}
break;
case stDeleteCharLeft: /* [Backspace] -- delete left */
if ( Pos )
{
--Move;
if ( Pos == max_width && OutStr[Pos] != (char)Fill )
OutStr[Pos] = Fill;
else if ( --Pos == PointNdx )
OutStr[--Pos] = Fill;
else
{
if ( Pos < PointNdx )
max_width = PointNdx - 1;
goto __MoveCharsToCursor;
}
}
break;
case stMoveToStart: /* [Home] -- start of field */
if ( Pos )
{
Pos = 0;
--Move;
}
break;
case stMoveCharLeft: /* [Left Arrow] -- move char lt */
if ( Pos )
{
if ( --Pos <= SignNdx )
Pos = 0;
--Move;
}
break;
case stMoveCharRight: /* [Right Arrow] -- move char rt */
if ( Pos < max_width )
{
++Pos;
++Move;
}
break;
case stMoveToEnd: /* [End] -- end of field */
if ( Pos < max_width )
{
Pos = max_width;
++Move;
}
break;
case stMoveWordLeft: /* [Ctrl Left] -- move word lt */
if ( Pos )
{
Pos = Pos > PointNdx + 1 ? PointNdx + 1 : 0 ;
--Move;
}
break;
case stMoveWordRight: /* [Ctrl Right] -- move word rt */
if ( Pos < max_width )
{
Pos = Pos < PointNdx ? PointNdx + 1 : max_width ;
++Move;
}
break;
case stDeleteWordLeft: /* [Ctrl L] -- delete word left */
if ( Pos == (PointNdx + 1) )
Pos = PointNdx - 1;
max_width = Pos;
Pos = Pos > PointNdx ? PointNdx + 1 : 0 ;
goto __DeleteWord;
case stDeleteWordRight: /* [Ctrl R] -- delete word right */
if ( Pos == (PointNdx - 1) )
Pos = PointNdx + 1;
if ( Pos < PointNdx )
max_width = PointNdx - 1; /* fall through to __DeleteWord */
case stDeleteToEnd: /* [Ctrl End] -- clear to end */
__DeleteWord:
;
memset( OutStr + Pos, Fill, max_width - Pos + 1 );
OutStr[PointNdx] = '.';
++Update;
break;
case stDeleteToStart: /* [Ctrl Home] -- clear to start */
max_width = Pos;
Pos = 0;
goto __DeleteWord;
case stDeleteAtCursor: /* [Del] -- delete at cursor */
if ( Pos < PointNdx )
max_width = PointNdx - 1;
++Update;
__MoveCharsToCursor:
;
memcpy( OutStr + Pos, OutStr + Pos + 1, max_width - Pos );
OutStr[max_width] = Fill;
break;
case stExitPlus: /* [Keypad +] -- special exit */
case stExitMinus: /* [Keypad -] -- special exit */
/****
If cursor is to right of sign position or Sign flag
is off, treat these keys as exits; otherwise convert
Chr to '+' or '-' and fall through to stCharMatch.
****/
if ( Pos > SignNdx || !Flags.Sign )
{
__FloatExit:
;
FloatFix( FLT_FIX, PointNdx );
FloatFix( FLT_PAD, 0 );
More = NO;
++Update;
break;
}
else
Chr = (State == stExitPlus) ? '+' : '-' ;
case stCharMatch: /* see if entry matches field */
if
(
isdigit( Chr )
||
( (Chr == '+' || Chr == '-') && Pos <= SignNdx && Flags.Sign )
||
( !Point && Chr == '.' )
)
{
if ( InBegin )
Pos = hFloatField( stFieldClear, 0 );
if ( Chr == '+' || Chr == '-' )
{
Sign = Chr;
SignNdx = Pos;
}
if ( Chr == '.' )
{
FloatFix( FLT_FIX, Pos );
Pos = PointNdx + 1;
memset( OutStr + Pos, Fill, Prec );
}
else
OutStr[Pos++] = Chr;
++Move;
} /* if (isdigit) */
else
State = stError;
break;
} /* switch */
if ( Pos >= Width )
Pos = Width - 1;
if ( Pos == PointNdx )
Pos += Move; /* move left or right past sign */
Point = (Pos >= PointNdx);
if ( Move )
{
/****
If the cursor has passed to the left of the sign (or
implied sign) position, FloatFix() moves the integer
portion of OutStr to the beginning of the field and
fills vacant digit positions with Fill.
****/
if ( Pos <= SignNdx )
Pos = FloatFix( FLT_MOV, PointNdx );
/****
If the cursor has passed to the right over the decimal
point, FloatFix() closes gaps in the integer portion of
OutStr and moves that part of the string adjacent to the
point. After the call to FloatFix(), all fill characters
to the left of the decimal point have been replaced by
digits, sign, or spaces, so FloatFix() is not called on
subsequent moves while the cursor is still to the right
of the decimal.
****/
if ( Move > 0 && Pos > PointNdx )
{
if ( memchr( OutStr, Fill, PointNdx ) )
FloatFix( FLT_FIX, PointNdx );
}
/****
If the cursor has passed to the left over the decimal
point, FloatFix() closes gaps in the decimal portion
of OutStr and pads it with zeros. After the call to
FloatFix(), all fill characters to the right of the
decimal point have been replaced by digits, so
FloatFix() is not called on subsequent moves while
the cursor is still to the left of the decimal.
****/
else if ( Move < 0 && Pos < PointNdx && old_pos > PointNdx )
{
if ( memchr( OutStr + PointNdx + 1, Fill, Prec ) )
FloatFix( FLT_PAD, PointNdx );
}
++Update;
Move = NO;
} /* if(Move) */
return( Pos );
} /**** hFloatField() ****/
/*************************************************************************
FloatFix()
Patches up the output string in floating-point fields.
*************************************************************************/
static int near pascal FloatFix
(
int Op, /* operation requested */
register int Pos /* index into string */
)
{
BYTE c